package com.qlh.camera.util;

import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import java.io.File;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 *作者：QLH on 2020-04-28
 *描述：图像的处理工具类
 */
public class NoBgUtil {

    /**采用本地opencv计算物体最小矩阵**/
    public Mat getCutRectFromLocal(String filePath,Mat dstMat) {
        Mat sourceMat;
        if (dstMat!=null){
            sourceMat = dstMat;
        }else {
            sourceMat = Imgcodecs.imread(filePath);
        }
        //转RGB
        Mat rgbMat = new Mat();
        Imgproc.cvtColor(sourceMat, rgbMat, Imgproc.COLOR_BGR2RGB);
        // 1. 中值模糊降噪处理;
        Imgproc.medianBlur(rgbMat, rgbMat, 7);
        // 2. 转灰度
        Imgproc.cvtColor(rgbMat, rgbMat, Imgproc.COLOR_BGRA2GRAY);
        // 3. 二值化:白变黑黑变白
        Imgproc.threshold(
            rgbMat, rgbMat, 90.0, 255.0,
            Imgproc.THRESH_BINARY|Imgproc.THRESH_OTSU //使用这种标志是，第三个参数thresh系统自动计算阈值
        );
        System.out.println(Imgproc.THRESH_BINARY|Imgproc.THRESH_OTSU);
        //去除背景
        Mat blackBg = new Mat();//将原图背景变成黑色
        Mat src2 = new Mat();
        List<Mat> list = new ArrayList<>();
        list.add(rgbMat);
        list.add(rgbMat);
        list.add(rgbMat);
        Core.merge(list, src2);//组成3通道
        Core.bitwise_and(sourceMat, src2, blackBg);//按位与操作，背景置黑
        src2.release();
        //4. 腐蚀
        Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(6.0, 5.0));
        Imgproc.erode(rgbMat, rgbMat, kernel, new Point(-1.0, -1.0), 4);
        //5. 膨胀 连接边缘
        Imgproc.dilate(rgbMat, rgbMat,new  Mat(),new  Point(-1.0, -1.0), 4, 1, new Scalar(1.0));
        //6. Canny边缘检测
        Imgproc.Canny(rgbMat, rgbMat, 10.0, 100.0, 5, true);
        // 7. 从二值图像中检索轮廓
        List<MatOfPoint> contours = new ArrayList<>();
        Imgproc.findContours(
            rgbMat, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE
        );
        rgbMat.release();
        // 8. 从集合中找合适的轮廓[宽高过半]
        List<Rect> matchRects = new ArrayList<>();//符合条件的矩形
        contours.forEach(it->{
            Rect rect = Imgproc.boundingRect(it);
            // 区域的宽高必须大于图片的一半
            if (rect.width > sourceMat.cols() / 2 && rect.height > sourceMat.rows() / 2) {
                matchRects.add(rect);
            }
        });

        //符合条件中面积最大的 matchRects.sortByDescending { it.area() }
        matchRects.stream().sorted(Comparator.comparing(Rect::area)).collect(Collectors.toList());
        sourceMat.release();
        if (matchRects.size() > 0) {
            Rect maxRect = matchRects.get(0);
            return cutOriginImageByRect(new DetectResult(maxRect.width, maxRect.height, maxRect.x, maxRect.y), blackBg);
        } else {
            return blackBg;
        }

    }

    //根据获取的最小轮廓矩阵裁剪黑色背景原图blackBgMat
    private Mat cutOriginImageByRect(DetectResult param,Mat blackBgMat) {
        //Log.e("111111",param.toString());
        if (blackBgMat != null) {
            Rect roiRect = new Rect(param.left, param.top, param.width, param.height);
            Mat roiMat = new Mat(blackBgMat, roiRect);//roiMat最终裁剪完成，黑色背景的图，使用它计算特征值
            blackBgMat.release();
            return roiMat;
        }else{
            return  null;
        }
    }
}